package com.xnet.datahandler.domain;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
import org.springframework.stereotype.Repository;

import com.xnet.datahandler.common.MultilevelNoGenerator;
import com.xnet.datahandler.common.Page;
import com.xnet.datahandler.enums.IDMode;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
* mysql数据仓库
* @author 目田
* 2016年12月22日
*/
@Repository
public class MysqlDatabaseRepository {
	
	private Logger logger = Logger.getLogger(getClass());
	
	public static final Integer PAGE_SIZE = 3;
	public static String groupByColumn = "{groupByColumn}";
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	/**
	 * 返回当前库下所有表
	 * @return
	 */
	public List<Map<String, Object>> getTables() {
		return jdbcTemplate.queryForList("show tables");
	}
	
	/**
	 * 获得tableName表的的所有列
	 * @param tableName
	 * @return
	 */
	public List<Map<String, Object>> getColumns(String tname) {
		return jdbcTemplate.queryForList("desc "+tname);
	}
	
	/**
	 * 以分页形式获取指定表数据
	 * @param tableName 表名
	 * @param pageNo 页码
	 * @param pageCount 每页显示数据行数
	 * @return
	 */
	public List<Map<String, Object>> getTableData(String tableName, Integer pageNo, Integer pageSize) {
		return this.getDataByPage("select * from " + tableName, pageNo, pageSize);
	}
	
	/**
	 * 以分页形式获得数据列表
	 * @param sql sql语句
	 * @param pageNo 页码
	 * @param pageCount 每页显示数据行数
	 * @return
	 */
	public List<Map<String, Object>> getDataByPage(String sql, Integer pageNo, Integer pageSize) {
		return new Page().query(sql, pageNo, pageSize, this.jdbcTemplate);
	}
	
	/**
	 * 按规则分批导入数据
	 * @param rule
	 * @return
	 */
	public Integer importDataFromGroupBy(ImportRule rule) throws Exception {

		//第一参数的上一次处理结果
		StringBuilder preQuerySqlResult = new StringBuilder();
		
		//外部来源读取计数器初始数值，现在这默认是1，写死的，应该配置从内存数据库或关系型数据库中读取
		Integer[] counter = new Integer[]{1};
		MultilevelNoGenerator generator = MultilevelNoGenerator.config(1, new Integer[]{3}, "", "0", counter);
		//返回值
		Integer res = 0;
		//页码
		Integer pageNo = -1;
		//当前页
		Integer currentIndex = 0;
		//查询语句
		StringBuilder sql =  new StringBuilder();
		sql.append("select ").append(rule.getGroupColumnName()).append(" from ").append(rule.getTableName());
		sql.append(" group by ").append(rule.getGroupColumnName()).append(" order by ").append(rule.getOrderColumnName()).append(" limit {page}");
		//查询结果集合
		List<Map<String, Object>> list = new ArrayList<>();
		//SQL分页部分limit语句的拼装
		StringBuilder page = new StringBuilder();
		
		//插入SQL
		StringBuilder insertSql = new StringBuilder();
		//占位符
		StringBuilder placeholder = new StringBuilder();
		//列
		StringBuilder columnString = new StringBuilder();
		//json格式待处理的列信息
		JSONArray columns = JSONArray.fromObject(rule.getJsonOtherColumn());
		//组装列
		for(Object object : columns) {
			JSONObject column = JSONObject.fromObject(object);
			columnString.append(",").append(column.get("selTargetOtherColumn"));
			placeholder.append(",?");
		}
		//拼装SQL语句
		insertSql.append("insert into ").append(rule.getSelectTargetTable()).append("(");
		insertSql.append(rule.getSelTargetColumn()).append(columnString);
		insertSql.append(")").append(" values(?").append(placeholder).append(")");
		logger.debug(insertSql.toString());
		
		while(list != null){
			//增加页码
			pageNo++;
			//计算当前起始位置
			currentIndex = pageNo * PAGE_SIZE;
			//组装查询SQL分页部分
			page.append(currentIndex).append(",").append(PAGE_SIZE);
			String newsql = sql.toString().replace("{page}", page.toString());
			//执行查询SQL
			list = this.jdbcTemplate.queryForList(newsql);
			
			//批量插入数据
			batchExecute(insertSql.toString(), list, rule, columns, generator, preQuerySqlResult);
			//重置变量
			page.delete(0, page.length());
			//处理是否继续循环
			if(list.size() <= 0 ) {
				list = null;
			}
		}
		res = 1;
		return res;
	}
	
	/**
	 * 批量插入数据
	 * @param list
	 * @param rule
	 * @return
	 * @author 徐目田
	 * 2016年12月27日
	 */
	private int[][] batchExecute(String sql, List<Map<String, Object>> list, ImportRule rule, JSONArray columns, MultilevelNoGenerator generator, StringBuilder preQuerySqlResult) throws Exception {
		//参数列表
		List<Object[]> params = new ArrayList<>();
		//单条SQL语句参数列表
		List<Object> tmpParams = new ArrayList<>();
		//循环获取数据
		for(Map<String, Object> map : list) {
			//当前列的值
			String columnValue = (String)map.get(rule.getColumnName());
			StringBuilder groupByColumns = new StringBuilder();
			groupByColumns.append("'");
			for(String key : map.keySet()) {
				groupByColumns.append(map.get(key));
			}
			groupByColumns.append("'");
			tmpParams.add(columnValue);
			for(Object object : columns) {
				StringBuilder sparam = new StringBuilder();
				JSONObject column = JSONObject.fromObject(object);
				//第一参数SQL语句的处理
				String querySql = column.getString("txtOtherSql");
				if(StringUtils.isNotEmpty(querySql)) {
					querySql = querySql.replace(groupByColumn, groupByColumns);
					Map<String, Object> fieldMap = this.jdbcTemplate.queryForMap(querySql);
					for(String key : fieldMap.keySet()) {
						//存当前第一参数的值
						StringBuilder s = new StringBuilder();
						s.append(fieldMap.get(key));
						
						
						if(IDMode.MULTIID.getId() == column.getInt("selIDMode")) {
							//判断第一参数的值是否发生了变化
							if(!s.toString().equals(preQuerySqlResult.toString())) {
								//第一参数发生变化说明开始迭代一个新组数据,所以重置编号
								generator.reset();
							}
							//清空preQuerySqlResult存入新的第一参数处理结果
							if(StringUtils.isNotEmpty(preQuerySqlResult.toString())) {
								preQuerySqlResult.delete(0, preQuerySqlResult.length());
							}
							preQuerySqlResult.append(s);
						}
						
						
						//待拼装参数
						sparam.append(s);
						
					}
				}
				//第二参数编号的处理
				if(column.getInt("selIDMode") > IDMode.NULL.getId()) {
					sparam.append(generator.getNumber());
				}
				String currentColumnValue = column.getString("txtOtherColumnValue");
				//第三参数设置值得处理
				if(StringUtils.isNotEmpty(currentColumnValue)) {
					sparam.append(currentColumnValue);
				}
				tmpParams.add(sparam.toString());
			}
			
			//单条SQL语句的参数数组
			Object[] param = tmpParams.toArray();
			//将参数加入参数列表
			params.add(param);
			tmpParams.clear();
			
			groupByColumns.delete(0, groupByColumns.length());
		}
		//执行批量插入数据
		return this.jdbcTemplate.batchUpdate(sql, params, list.size(),
				new ParameterizedPreparedStatementSetter<Object[]>() {
					@Override
					public void setValues(PreparedStatement ps, Object[] param) throws SQLException {
						for (int i = 0; i < param.length; i++) {
							ps.setObject( (i + 1), param[i]);
						}
					}
				});
	}
	
}
